using System;
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace Gj
{
    public class GameUISpace : BaseUISpace
    {
        [SerializeField] private bool screenMove;
        [SerializeField] private bool screenSize;
        [SerializeField] private bool screenRound;
        [SerializeField] private bool screenClick;
        [SerializeField] private bool screenDrag;

        public EventSystem eventSystem;
        public GraphicRaycaster graphicRaycaster;

        private float touchStartTime;
        private float touchEndTime;
        private bool isDouble;
        private bool isRight;
        private bool isTouch;
        private Vector2 touchPoint;

        protected bool disabled = true;

        private bool screenDragTouch;
        private bool screenMoveTouch;
        private Vector2 moveInfo;
        private Vector2 startInfo;

        private bool otherTouch;
        private bool touch;
        private bool touchDown;
        private bool touchUp;
        private int touchIndex = -1;
        private int touchId = -1;
        private int touchMoveId = -1;

        protected virtual void Start()
        {
#if UNITY_EDITOR
            ScreenHandle.scale = true;
            ScreenHandle.boundary = false;
            ScreenHandle.move = true;
            ScreenHandle.drag = false;
#elif UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX
            ScreenHandle.scale = true;
            ScreenHandle.boundary = true;
            ScreenHandle.move = true;
            ScreenHandle.drag = false;
#elif UNITY_IPHONE || UNITY_ANDROID
            ScreenHandle.scale = false;
            ScreenHandle.boundary = false;
            ScreenHandle.move = false;
            ScreenHandle.drag = false;
#else
#endif
        }

        // Update is called once per frame
        protected override void Update()
        {
            base.Update();
            
#if UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX || UNITY_EDITOR
            PCModel();
#elif UNITY_IPHONE || UNITY_ANDROID
            MobileModel();
#else
            MobileModel();
#endif

            if (ScreenHandle != null) ScreenHandle.Handle();
            
            // SystemInput.rUI = RUITypte.None;
            
            if (screenDrag) ScreenDrag();
            if (screenMove) ScreenMove();
            if (screenSize) ScreenSize();
            if (screenRound) ScreenRound();
            
            OnUpdate();
        }

        protected virtual void OnUpdate()
        {
        }

        private void PCModel()
        {
            SaveMouse();

            if (screenClick) ScreenMouseClick();
            
            // TODO 鼠标场景边缘移动            
            // if (Game.GetDevicePlatform() == "PC")
            // {
            //     freeCamera.ChangeMove(x, y);
            // }
        }

        private void MobileModel()
        {
            SaveTouch();

            if (screenClick) ScreenTouchClick();

#if UNITY_ANDROID
            if (Input.GetKeyDown(KeyCode.Escape)) ScreenBack();
#endif
        }

        protected void OtherDragStart()
        {
#if UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX || UNITY_EDITOR
            OtherMouseStart();
#elif UNITY_IPHONE || UNITY_ANDROID
            OtherTouchStart();
#else
            OtherTouchStart();
#endif
        }

        protected void OtherDragEnd()
        {
#if UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX || UNITY_EDITOR
            OtherMouseEnd();
#elif UNITY_IPHONE || UNITY_ANDROID
            OtherTouchEnd();
#else
            OtherTouchEnd();
#endif
        }

        private void OtherMouseStart()
        {
            
        }

        private void OtherMouseEnd()
        {
            
        }

        private void SaveMouse()
        {
            SystemInput.cp = Input.mousePosition;
            if (touchUp) touchUp = false;
            if (Input.GetMouseButtonDown(0))
            {
                SystemInput.rUI = CheckRUI(SystemInput.cp);
                startInfo = SystemInput.cp;
                if (ScreenCheckDrag(SystemInput.cp.x, SystemInput.cp.y))
                {
                    ScreenHandle.drag = false;
#if UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX || UNITY_EDITOR
                    ScreenHandle.boundary = true;
#endif
                    touchDown = true;
                }
                else
                {
                    ScreenHandle.drag = true;
                    ScreenHandle.boundary = false;
                }
            }

            if (Input.GetMouseButton(0))
            {
                if (!Input.GetMouseButtonDown(0) && touchDown)
                {
                    touchDown = false;
                    touch = true;
                }
            }

            if (Input.GetMouseButtonUp(0))
            {
                ScreenHandle.drag = false;
#if UNITY_EDITOR
                ScreenHandle.boundary = false;
#elif UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX
                ScreenHandle.boundary = true;
#endif
                if (touch)
                {
                    touch = false;
                    touchUp = true;
                }
            }
        }

        private void OtherTouchStart()
        {
            otherTouch = true;
            if (Input.touchCount == 1)
            {
                SystemInput.rUI = RUITypte.Drag;
                ScreenHandle.move = false;
                ScreenHandle.boundary = true;
                touchIndex = 0;
                touchMoveId = -1;
                touchId = Input.GetTouch(touchIndex).fingerId;
                ScreenHandle.moveIndex = -1;
            }
            else if (Input.touchCount == 2)
            {
                touchIndex = touchMoveId == Input.GetTouch(1).fingerId ? 0 : 1;
                ScreenHandle.move = true;
                ScreenHandle.scale = false;
                ScreenHandle.boundary = false;
                ScreenHandle.moveIndex = touchIndex == 0 ? 1 : 0;
                touchId = Input.GetTouch(touchIndex).fingerId;
            }

            SaveTouch();
        }

        private void OtherTouchEnd()
        {
            // Debug.LogErrorFormat("OtherTouchEnd: {0}", Input.touchCount);
            // if (Input.touchCount == 1)
            // {
            //     touchIndex = 1;
            //     ScreenHandle.move = true;
            //     ScreenHandle.moveIndex = 0;   
            //     touchMoveId = Input.GetTouch(0).fingerId;                 
            // }
            otherTouch = false;
        }

        private void SaveTouch()
        {
            if (Input.touchCount > 0 && touchIndex == -1)
            {
                SystemInput.cp = Input.GetTouch(0).position;
                SystemInput.rUI = CheckRUI(SystemInput.cp);
                touchIndex = 0;
                startInfo = SystemInput.cp;
                // Debug.LogErrorFormat("TouchStart: {0} {1}", touchMoveId, SystemInput.rUI.ToString());
            }

            if (touchUp) touchUp = false;

            if (!otherTouch)
            {
                // Debug.LogErrorFormat("{0} {1} {2} {3}", touchMoveId, Input.touchCount, touch, touchDown);
                if (touchDown && Input.touchCount > 0)
                {
                    touch = true;
                    touchDown = false;
                }

                // Debug.LogErrorFormat("Touch: {0} {1} {2}", touch, touchDown, touchUp);
                if (!touch && !touchDown && Input.touchCount > 0)
                {
                    // Debug.LogErrorFormat("Touch: {0} {1} {2} {3}", Input.touchCount, touchId, touchMoveId, touchIndex);
                    if (Input.touchCount == 1 && touchIndex == 0)
                    {
                        // Debug.LogErrorFormat("Touch: {0}", 1);
                        if (ScreenCheckDrag(Input.GetTouch(0).position.x,
                                Input.GetTouch(0).position.y))
                        {
                            // Debug.LogErrorFormat("Touch: {0}", 2);
                            touchDown = true;
                            ScreenHandle.boundary = true;
                            ScreenHandle.move = false;
                            touchMoveId = -1;
                            touchId = Input.GetTouch(0).fingerId;
                        }
                        else
                        {
                            // Debug.LogErrorFormat("Touch: {0}", 3);
                            ScreenHandle.boundary = false;
                            ScreenHandle.move = true;
                            ScreenHandle.moveIndex = 0;
                            touchMoveId = Input.GetTouch(0).fingerId;
                            touchId = -1;
                            // Debug.LogErrorFormat("touchMoveId: {0}", touchMoveId);
                            touchIndex = 1;
                        }
                    }
                    else if (Input.touchCount == 2 && touchIndex == 0)
                    {
                        // Debug.LogErrorFormat("TouchScale");
                        ScreenHandle.boundary = false;
                        ScreenHandle.move = false;
                        ScreenHandle.scale = true;
                        touchIndex = 2;
                        touchMoveId = -1;
                        touchId = -1;
                    }
                    else if (Input.touchCount == 2 && touchIndex == 1)
                    {
                        // Debug.LogErrorFormat("Touch: {0} {1}", touchIndex, touchMoveId);
                        if (touchMoveId == Input.GetTouch(touchIndex).fingerId) touchIndex = 0;
                        if (ScreenCheckDrag(Input.GetTouch(touchIndex).position.x,
                                Input.GetTouch(touchIndex).position.y))
                        {
                            // Debug.LogErrorFormat("Touch: {0}", 4);
                            touchDown = true;
                            ScreenHandle.move = true;
                            ScreenHandle.boundary = false;
                            ScreenHandle.moveIndex = touchIndex == 0 ? 1 : 0;
                            touchId = Input.GetTouch(touchIndex).fingerId;
                        }
                        else
                        {
                            // Debug.LogErrorFormat("Touch: {0}", 5);
                            ScreenHandle.boundary = false;
                            ScreenHandle.move = false;
                            ScreenHandle.scale = true;
                            touchIndex = 2;
                            touchMoveId = -1;
                            touchId = -1;
                        }
                    }
                    else if (touchIndex == 2 && Input.touchCount == 1)
                    {
                        // Debug.LogErrorFormat("Touch: {0}", 6);
                        ScreenHandle.move = true;
                        ScreenHandle.boundary = false;
                        ScreenHandle.scale = false;
                        ScreenHandle.moveIndex = 0;
                        touchMoveId = Input.GetTouch(0).fingerId;
                        // Debug.LogErrorFormat("touchMoveId: {0}", touchMoveId);
                        touchIndex = 1;
                        touchId = -1;
                    }
                }
                if (touch)
                {
                    // Debug.LogErrorFormat("Touch: moveId:{0}", touchMoveId);
                    if (touchMoveId == -1 && Input.touchCount == 2)
                    {
                        // Debug.LogErrorFormat("Touch: {0}", 7);
                        if (touchId == Input.GetTouch(0).fingerId)
                        {
                            touchIndex = 0;
                            touchId = Input.GetTouch(0).fingerId;
                            ScreenHandle.moveIndex = 1;
                            touchMoveId = Input.GetTouch(1).fingerId;
                        }
                        else
                        {
                            touchIndex = 1;
                            touchId = Input.GetTouch(1).fingerId;
                            ScreenHandle.moveIndex = 0;
                            touchMoveId = Input.GetTouch(0).fingerId;
                        }
                        ScreenHandle.boundary = false;
                        ScreenHandle.move = true;
                        // Debug.LogErrorFormat("Touch: {0} {1}", touchId, touchMoveId);
                    }
                    else if (touchMoveId > -1 && Input.touchCount == 1)
                    {
                        if (touchMoveId == Input.GetTouch(0).fingerId)
                        {
                            // Debug.LogErrorFormat("Touch: {0}", 8);
                            touch = false;
                            touchUp = true;
                            touchIndex = 1;
                            ScreenHandle.boundary = false;
                            ScreenHandle.move = true;
                            ScreenHandle.moveIndex = 0;
                        }
                        else
                        {
                            // Debug.LogErrorFormat("Touch: {0}", 9);
                            touchIndex = 0;
                            touchId = Input.GetTouch(0).fingerId;
                            ScreenHandle.move = false;
                            ScreenHandle.boundary = true;
                            touchMoveId = -1;
                        }
                    }
                }
            }
            else
            {
                // Debug.LogErrorFormat("{0} {1}", touchMoveId, Input.touchCount);
                if (touchMoveId == -1 && Input.touchCount == 2)
                {
                    // Debug.LogErrorFormat("Touch: {0}", 11);
                    if (touchId == Input.GetTouch(0).fingerId)
                    {
                        touchIndex = 0;
                        touchId = Input.GetTouch(0).fingerId;
                        ScreenHandle.moveIndex = 1;
                        touchMoveId = Input.GetTouch(1).fingerId;
                    }
                    else
                    {
                        touchIndex = 1;
                        touchId = Input.GetTouch(1).fingerId;
                        ScreenHandle.moveIndex = 0;
                        touchMoveId = Input.GetTouch(0).fingerId;
                    }
                    // Debug.LogErrorFormat("Touch: {0} {1}", touchId, touchMoveId);
                    ScreenHandle.boundary = false;
                    ScreenHandle.move = true;
                }
                else if (touchMoveId > -1 && Input.touchCount == 1)
                {
                    if (touchMoveId == Input.GetTouch(0).fingerId)
                    {
                        // Debug.LogErrorFormat("Touch: {0}", 12);
                        touch = false;
                        touchUp = true;
                        touchIndex = 1;
                        touchId = -1;
                        ScreenHandle.boundary = false;
                        ScreenHandle.move = true;
                        ScreenHandle.moveIndex = 0;
                        touchMoveId = Input.GetTouch(0).fingerId;
                    }
                    else
                    {
                        // Debug.LogErrorFormat("Touch: {0}", 13);
                        touchIndex = 0;
                        touchId = Input.GetTouch(0).fingerId;
                        ScreenHandle.move = false;
                        ScreenHandle.boundary = true;
                        touchMoveId = -1;
                    }
                }
            }
            
            if (Input.touchCount > 0 && touchIndex <= Input.touchCount - 1) SystemInput.cp = Input.GetTouch(touchIndex).position;

            if (Input.touchCount == 0)
            {
                if (touchDown)
                {
                    // Debug.LogErrorFormat("Touch: {0}", 14);
                    // Debug.LogErrorFormat("touchDown: {0}", touchMoveId);
                    touchDown = false;
                    touchUp = true;
                }

                if (touch)
                {
                    // Debug.LogErrorFormat("Touch: {0}", 15);
                    // Debug.LogErrorFormat("touch: {0}", touchMoveId);
                    touch = false;
                    touchUp = true;
                }

                if (touchIndex != -1)
                {
                    // Debug.LogErrorFormat("TouchEnd: {0}", touchMoveId);
                    touchIndex = -1;
                    touchId = -1;
                    touchMoveId = -1;
                    ScreenHandle.move = false;
                    ScreenHandle.scale = false;
                    ScreenHandle.boundary = false;
                }
            }
        }

        private RUITypte CheckRUI(Vector2 p)
        {
            var eventData = new PointerEventData(eventSystem);
            eventData.pressPosition = p;
            eventData.position = p;

            var list = new List<RaycastResult>();
            graphicRaycaster.Raycast(eventData, list);
            if (list.Count > 0)
            {
                for (var i = 0; i < list.Count; i++)
                    if (list[i].gameObject.layer == 5)
                        return RUITypte.None;
                return RUITypte.All;
            }

            return RUITypte.All;
        }

        private void ScreenMove()
        {
            // if (Input.touchCount > 1) SystemInput.rUI = RUITypte.All;
            if (SystemInput.rUI != RUITypte.All && SystemInput.rUI != RUITypte.Drag) return;
            // Debug.LogErrorFormat("ScreenMove: {0} {1} {2} {3}", SystemInput.sm, SystemInput.sx, SystemInput.sy, moveInfo);
            if (SystemInput.sm)
            {
                if (!screenMoveTouch)
                {
                    ScreenMoveEnter();
                    screenMoveTouch = true;
                    moveInfo = Vector2.zero;
                }

                moveInfo += new Vector2(SystemInput.sx, SystemInput.sy);
                // Debug.LogErrorFormat("ScreenMove: {0} {1} {2}", SystemInput.sx, SystemInput.sy, moveInfo);
                if (Vector2.Distance(moveInfo, Vector2.zero) > 0) ScreenMove(SystemInput.sx, SystemInput.sy);
            }
            else
            {
                if (screenMoveTouch)
                {
                    ScreenMoveExit();
                    screenMoveTouch = false;
                    moveInfo = Vector2.zero;
                }
            }
            if (SystemInput.sb) ScreenBoundary(SystemInput.bx, SystemInput.by);
        }

        private void ScreenSize()
        {
            if (SystemInput.rUI != RUITypte.All && SystemInput.rUI != RUITypte.Drag) return;
            if (SystemInput.si != 0) ScreenSize(SystemInput.si * -1);
        }

        private void ScreenRound()
        {
            if (SystemInput.rUI != RUITypte.All && SystemInput.rUI != RUITypte.Drag) return;
            if (SystemInput.sr != 0) ScreenRound(SystemInput.sr);
        }

        protected bool IsDrag()
        {
            if (!IsMove()) return false;
            if (touchStartTime + SystemInput.clickTime < Time.time) return true;
            return false;
        }

        protected bool IsClick()
        {
            if (IsMove()) return false;
            if (Time.time < touchStartTime + SystemInput.clickTime) return true;
            return false;
        }

        protected bool IsDoubleClick()
        {
            if (IsMove()) return false;
            if (Time.time < touchStartTime + SystemInput.clickTime) return true;
            return false;
        }

        protected bool IsMove()
        {
            // Debug.LogErrorFormat("IsMove: info: {0} dis: {1}  distance:{2}", startInfo, Vector2.Distance(SystemInput.cp, startInfo), SystemInput.moveDistance);
            return Vector2.Distance(SystemInput.cp, startInfo) > SystemInput.moveDistance;
        }

        private void ScreenDrag()
        {
            if (SystemInput.rUI != RUITypte.All && SystemInput.rUI != RUITypte.Drag) return;
            // Debug.LogErrorFormat("ScreenDrag: {0} {1} {2}", touchDown, touch, touchUp);
            if (touchDown)
                if (!screenDragTouch)
                {
                    ScreenDragEnter();
                    screenDragTouch = true;
                }

            if (touch && screenDragTouch) ScreenDrag(SystemInput.cp.x, SystemInput.cp.y);

            if (touchUp)
                if (screenDragTouch)
                {
                    ScreenDragExit();
                    screenDragTouch = false;
                }
        }

        private void ScreenMouseClick()
        {
            if (SystemInput.rUI != RUITypte.All && SystemInput.rUI != RUITypte.Click) return;
            if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1))
            {
                touchStartTime = Time.time;
            }

            if ((Input.GetMouseButtonUp(0) || Input.GetMouseButtonUp(1)))
            {
                touchPoint = SystemInput.cp;
                touchEndTime = Time.time;
            }

            if (Input.GetMouseButtonUp(0))
            {
                isRight = false;
            }

            if (Input.GetMouseButtonUp(1))
            {
                isRight = true;
            }

            switch (CheckClick())
            {
                case UIEvent.Click:
                    ScreenClick(touchPoint.x, touchPoint.y);
                    if (isRight) ScreenRightClick(touchPoint.x, touchPoint.y);
                    break;
                case UIEvent.DoubleClick:
                    ScreenDoubleClick(touchPoint.x, touchPoint.y);
                    break;
            }
        }

        private void ScreenTouchClick()
        {
            if (SystemInput.rUI != RUITypte.All && SystemInput.rUI != RUITypte.Click) return;
            if (Input.touchCount > 0 && !isTouch)
            {
                touchStartTime = Time.time;
            }

            if (Input.touchCount == 0 && isTouch)
            {
                touchPoint = SystemInput.cp;
                touchEndTime = Time.time;
            }

            isTouch = Input.touchCount > 0;

            switch (CheckClick())
            {
                case UIEvent.Click:
                    ScreenClick(touchPoint.x, touchPoint.y);
                    break;
                case UIEvent.DoubleClick:
                    ScreenDoubleClick(touchPoint.x, touchPoint.y);
                    break;
            }
        }

        private UIEvent CheckClick()
        {
            if (touchEndTime > 0 && touchStartTime > 0)
            {
                if (IsMove())
                {
                    touchStartTime = 0;
                    touchEndTime = 0;
                    return UIEvent.None;
                }
                // Debug.LogErrorFormat("CheckClick: {0} {1}", touchStartTime, touchEndTime);
                if (touchEndTime > touchStartTime)
                {
                    // 判断单击双击
                    if (touchEndTime - touchStartTime > SystemInput.clickTime)
                    {
                        // 超过点击时间取消
                        touchEndTime = 0;
                        touchStartTime = 0;
                        isDouble = false;
                    }
                    else if (Time.time - touchEndTime > SystemInput.waitTime)
                    {
                        // 超过等待双击时间 则确定为单击
                        touchEndTime = 0;
                        touchStartTime = 0;
                        isDouble = false;
                        return UIEvent.Click;
                    }
                    else if (touchEndTime - touchStartTime < SystemInput.clickTime)
                    {
                        if (isDouble)
                        {
                            // 如果是第二次点击 直接判断为双击
                            touchEndTime = 0;
                            touchStartTime = 0;
                            isDouble = false;
                            return UIEvent.DoubleClick;
                        }
                    }
                }
                else if (touchStartTime > touchEndTime)
                {
                    //判断是否符合第二次点击
                    if (touchStartTime - touchEndTime < SystemInput.waitTime) isDouble = true;
                }
            }

            return UIEvent.None;
        }
        
        
            // if (endTime == 0 && startTime > 0 && Time.time - startTime > SystemInput.loopTime)
            // {
            //     endTime = 0;
            //     startTime = 0;
            //     d = false;
            //     Emit(UIEvent.LongPress);
            //     return;
            // }
            //
            // if (endTime > 0 && startTime > 0)
            // {
            //     if (endTime > startTime)
            //     {
            //         // 判断单击双击
            //         if (endTime - startTime > SystemInput.clickTime)
            //         {
            //             // 超过点击时间取消
            //             endTime = 0;
            //             startTime = 0;
            //             d = false;
            //         }
            //         else if (Time.time - endTime > SystemInput.waitTime || click)
            //         {
            //             // 超过等待双击时间 则确定为单击
            //             endTime = 0;
            //             startTime = 0;
            //             d = false;
            //             Emit(UIEvent.Click);
            //
            //             if (soundType != SoundType.None)
            //                 Game.single.PlayEFF(soundType);
            //             else if (clip != null) Game.single.PlayEFF(clip);
            //         }
            //         else if (endTime - startTime < SystemInput.clickTime)
            //         {
            //             if (d)
            //             {
            //                 // 如果是第二次点击 直接判断为双击
            //                 endTime = 0;
            //                 startTime = 0;
            //                 d = false;
            //                 Emit(UIEvent.DoubleClick);
            //
            //                 if (soundType != SoundType.None)
            //                     Game.single.PlayEFF(soundType);
            //                 else if (clip != null) Game.single.PlayEFF(clip);
            //             }
            //         }
            //     }
            //     else if (startTime > endTime)
            //     {
            //         //判断是否符合第二次点击
            //         if (startTime - endTime < SystemInput.waitTime) d = true;
            //     }
            // }

        protected virtual void ScreenMoveEnter()
        {
        }

        protected virtual void ScreenMove(float x, float y)
        {
        }

        protected virtual void ScreenBoundary(float x, float y)
        {
        }

        protected virtual void ScreenMoveExit()
        {
        }

        // true 为选中无法移动  false 为无选中可以移动
        protected virtual bool ScreenCheckDrag(float x, float y)
        {
            return true;
        }

        protected virtual void ScreenDragEnter()
        {
        }

        protected virtual void ScreenDrag(float x, float y)
        {
        }

        protected virtual void ScreenDragExit()
        {
        }

        protected virtual void ScreenSize(float size)
        {
        }

        protected virtual void ScreenRound(float angle)
        {
        }

        protected virtual void ScreenClick(float x, float y)
        {
        }

        protected virtual void ScreenDoubleClick(float x, float y)
        {
        }

        protected virtual void ScreenRightClick(float x, float y)
        {
        }

        protected virtual void ScreenBack()
        {
        }

        public override void StartPlay()
        {
            disabled = false;
        }

        public override void EndPlay()
        {
            disabled = true;
        }
    }
}